package test;

import java.util.HashSet;
import java.util.Set;

import org.junit.Assert;
import org.junit.Before;

import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.server.ServiceLayer;
import com.google.web.bindery.requestfactory.server.SimpleRequestProcessor;
import com.google.web.bindery.requestfactory.server.testing.InProcessRequestTransport;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.vm.RequestFactorySource;



public class GWTCollectionPropertyBug {

	
	public static class Parent extends Base {
		Set<Child> children = new HashSet<Child>();

		public Set<Child> getChildren() {
			return children;
		}

		public void setChildren(Set<Child> children) {
			this.children = children;
		}
		
		public static Parent getInstanceWithChildren() {
			Parent p = new Parent();
			Child c = new Child();
			p.getChildren().add(c);
			return p;
		}
		
		public static Parent getInstanceWithoutChildren() {
			Parent p = new Parent();
			return p;
		}
		
	}
	
	public static class Child extends Base {
	}

	//@Test
	public void testWithoutChildren() {
		requestFactory.request().getInstanceWithoutChildren().with("children").fire(new Receiver<ParentProxy>() {
			@Override
			public void onSuccess(ParentProxy response) {
				ParentRequest rc = requestFactory.request();
				
				Assert.assertFalse(rc.isChanged());
				rc.edit(response);
				Assert.assertFalse(rc.isChanged());
			}
		});
	}

	//@Test
	public void testWithChildren() {
		requestFactory.request().getInstanceWithChildren().with("children").fire(new Receiver<ParentProxy>() {
			@Override
			public void onSuccess(ParentProxy response) {
				ParentRequest rc = requestFactory.request();
				
				Assert.assertFalse(rc.isChanged());
				rc.edit(response);
				Assert.assertFalse(rc.isChanged()); // failure
			}
		});
	}
	
	
	@ProxyFor(Parent.class)
	public static interface ParentProxy extends EntityProxy {

		public Set<ChildProxy> getChildren();

		public void setChildren(Set<ChildProxy> children);
		
	}

	@ProxyFor(Child.class)
	public static interface ChildProxy extends EntityProxy {
	}
	
	public static interface TestRequestFactory extends RequestFactory {

		ParentRequest request();
	
	}
	
	@Service(Parent.class)
	public static interface ParentRequest extends RequestContext {
		Request<ParentProxy> getInstanceWithChildren();
		Request<ParentProxy> getInstanceWithoutChildren();
	}

	@Before
	public void init() {
		ServiceLayer serviceLayer = ServiceLayer.create();
		SimpleRequestProcessor processor = new SimpleRequestProcessor(serviceLayer);
		EventBus eventBus = new SimpleEventBus();
		requestFactory = RequestFactorySource.create(TestRequestFactory.class);
		requestFactory.initialize(eventBus, new InProcessRequestTransport(processor));
	}

	private TestRequestFactory requestFactory;

	public static class Base {
		Long id;
		Integer version;
		public Long getId() {
			return id;
		}
		public void setId(Long id) {
			this.id = id;
		}
		public Integer getVersion() {
			return version;
		}
		public void setVersion(Integer version) {
			this.version = version;
		}

		public static Parent findParent(Long id) {
			return null;
		}

		public static Child findChild(Long id) {
			return null;
		}
	}
	
}
